package netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.Attribute;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

@ChannelHandler.Sharable
public class ServerHandler implements ChannelInboundHandler {

    ServerHandler() {
        System.out.println("server handler construct");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        Attribute<String> test = ctx.channel().attr(NettyTest.test);
        System.out.println(test.get());
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req, StandardCharsets.UTF_8);
System.out.println(body);
        String respStr = "hello, client " + body;
        ByteBuf resp = Unpooled.copiedBuffer(respStr.getBytes());
        ctx.channel().eventLoop().scheduleAtFixedRate(() -> System.out.println("不耗时任务"), 6, 6, TimeUnit.HOURS);
        // 如果this.executor为null，就返回channel().eventLoop()，所以如果执行好使任务一定要在addLast时添加一个DefaultEventLoopGroup
        ctx.executor().scheduleAtFixedRate(() -> System.out.println("耗时任务"), 6, 6, TimeUnit.HOURS);
        // 前者从当前Handler开始写出，后者从tail开始
//        ctx.writeAndFlush(resp);
        ctx.pipeline().writeAndFlush(resp);
//                .addListener(ChannelFutureListener.CLOSE);//加上这句会自动关闭客户端
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext channelHandlerContext) throws Exception {
        // 当所有可读的字节都已经从channel中读取之后，将会调用该回调方法；
        // 所以，可能在channelReadComplete()被调用之前看到多次调用channelRead(...)
        System.out.println("channelReadComplete");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 在读取操作期间，有异常抛出时会调用
        cause.printStackTrace();
        ctx.close();
    }

    @Override
    public void handlerAdded(ChannelHandlerContext channelHandlerContext) throws Exception {

    }

    @Override
    public void handlerRemoved(ChannelHandlerContext channelHandlerContext) throws Exception {

    }

    /** 不会被多个线程请求，所以时线程安全的 */
    private int idx = 0;

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) {
        // 每次都是打印 1
        System.out.println(++idx);
        ctx.fireChannelRegistered();
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) {
        System.out.println(--idx);
        ctx.fireChannelUnregistered();
    }

    @Override
    public void channelActive(ChannelHandlerContext channelHandlerContext) throws Exception {

    }

    @Override
    public void channelInactive(ChannelHandlerContext channelHandlerContext) throws Exception {

    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (IdleState.READER_IDLE.equals(event.state())) {
                ctx.close();
            }
        }
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext channelHandlerContext) throws Exception {

    }
}
